﻿@using HardHatCore.ApiModels.Shared;
@using HardHatCore.HardHatC2Client.Models;
@using HardHatCore.HardHatC2Client.Pages;
@using HardHatCore.HardHatC2Client.Services;
@using System.Diagnostics;
@inject IJSRuntime JSRuntime


<MudDynamicTabs @ref="@DynamicTabs" Elevation="4" PanelClass="px-4 py-6" Rounded="true" ApplyEffectsToContainer="true"AddTab="AddTabCallback" CloseTab="@((panel) => CloseTabCallback(panel))" 
    @bind-ActivePanelIndex="UserIndex"AddIconToolTip="Click here to add a new tab" CloseIconToolTip="Close this tab. All data will be lost">
    
    @foreach (var item in UserTabs)
    {
        <MudTabPanel Text="@item.Name" Tag="@item.TabId">
            <MudCard Class="" Style=" background:#111111; overflow-y:auto" Outlined="true">
                <!--This is the parent card  -->
                <MudCardContent Style="background:#111111; color:white; height:800px">
                    @if (item.Content.Any())
                    {
                        @foreach (InteractiveTerminalCommand currenttask in item.Content.ToList())
                        {
                            <MudExpansionPanels Style="background:#32333d; color:white;" MultiExpansion="true">
                                <InteractiveTerminalContent currenttask="@currenttask" item="@item"></InteractiveTerminalContent>
                            </MudExpansionPanels>
                        }
                    }
                </MudCardContent>
            </MudCard>
            <EditForm Context="EditFormContext" Model="item" OnValidSubmit="@HandleSubmit">
                <div class="d-flex mb-xl-5">
                    <MudAutocomplete @ref="mudauto" @bind-value=CommandText Adornment="Adornment.Start" CoerceText="false" CoerceValue="true" AdornmentIcon="@Icons.Material.Filled.Terminal" T="string" Label="Command" Immediate="true" Clearable="true"
                                     Margin="Margin.Dense" Variant="Variant.Outlined" ResetValueOnEmptyText="true" TextUpdateSuppression=@TextSuppersion KeyDownPreventDefault="true" KeyUpPreventDefault="true" OnKeyUp="@((e)=>OnShowCommandHistory(e,item))">
                                     </MudAutocomplete>
                 
                    <MudButton style="background:var(--font-color);color:var(--background)" OnClick=HandleSubmit Variant="Variant.Filled" Class="ml-auto">Send</MudButton>
                @if(IsEnterkey)
                    {
                        Task.Run(async () => await Send(item.TabId));
                        IsEnterkey = false;
                    }
                </div>
            </EditForm>
        </MudTabPanel>
    }
</MudDynamicTabs>

@code {
    [Inject]
    private IDialogService DialogService { get; set; }

    public class TabView
    {
        public string Name { get; set; }
        public List<InteractiveTerminalCommand> Content { get; set; }
        public string TabId { get; set; }
    }

    public MudDynamicTabs? DynamicTabs;
    private MudAutocomplete<string> mudauto { get; set; }
    public static List<TabView> UserTabs = new();
    public static int UserIndex = 0;
    private bool _updateIndex = false;
    bool success;
    string[] errors;
    MudForm? form;
    public string CommandText = null;
    public static string UserInput { get; set; }
    private bool IsEnterkey { get; set; } = false;
    private static bool TextSuppersion = true;
    private static int HistoryIndex = 1;
    private static Stopwatch stopwatch = new Stopwatch();

    private void AddTabCallback()
    {
        TabView newtab = new TabView { Name = $"Terminal {UserTabs.Count() + 1}", Content = new List<InteractiveTerminalCommand>(), TabId = Guid.NewGuid().ToString() };
        UserTabs.Add(newtab);
        //the tab becomes available after it is rendered. Hence, we can't set the index here
        _updateIndex = true;
        HardHatHubClient._hub.CreateTabViewObject(newtab);
        InteractiveTerminalCommand command = new InteractiveTerminalCommand() { Command = UserInput, TabId = newtab.TabId };
        Task.Run(()=>ExecuteTerminalCommand(command.TabId));
    }

    private void CloseTabCallback(MudTabPanel panel)
    {
        var tabView = UserTabs.FirstOrDefault(x => x.TabId == (string)panel.Tag);
        if (tabView != null)
        {
            UserTabs.Remove(tabView);
            _updateIndex = true;
        }
    }

    public async Task HandleSubmit()
    {
        if (!String.IsNullOrWhiteSpace(CommandText))
        {
            UserInput = CommandText;
            CommandText = "";      // sets text back to empty
            TextSuppersion = false; //allows text box to be updated
            await mudauto.Clear();
            Thread.Sleep(5);
            IsEnterkey = true;
            TextSuppersion = true; // reset so textbox can be typed in without autoclearing until submission
            HistoryIndex = 1;
        }
    }

    private async Task Send(string tabid)
    {
        InteractiveTerminalCommand command = new InteractiveTerminalCommand() { Command = UserInput, TabId = tabid };
        TabView tab = UserTabs.Where(x => x.TabId == command.TabId).ToList()[0];
        tab.Content.Add(command);
        await SendTerminalCommand(command.Command, command.TabId);
        command.Output = await GetTerminalOutput(command.TabId);
        await HardHatHubClient._hub.CreateTerminalObject(command);
    }

    public static async Task UpdateTabContent(InteractiveTerminalCommand command)
    {
        TabView tab = UserTabs.Where(x => x.TabId == command.TabId).ToList()[0];
        if(tab.Content.Select(x=>x.Id == command.Id).ToList()[0])
        {
            InteractiveTerminalCommand currentCommand = tab.Content.Where(x => x.Id == command.Id).ToList()[0];
            currentCommand.Output = command.Output;
        }
    }

    private async Task ExecuteTerminalCommand(string TerminalId)
    {
        await Utilities.terminalCommandRecording.TerminalCommandExecute(TerminalId); 
    }

    private async Task<string> GetTerminalOutput(string tabid)
    {
        List<string> outputs = new();
        while(Utilities.terminalCommandRecording.TerminalOutput[tabid].IsEmpty)
        {
            await Task.Delay(100);
        }
        while(!Utilities.terminalCommandRecording.TerminalOutput[tabid].IsEmpty)
        {
            //trying to give queue a second to fill up with all the results from the command run
            await Task.Delay(1000);
            Utilities.terminalCommandRecording.TerminalOutput[tabid].TryDequeue(out string output);
            outputs.Add(output);
        }
        if (outputs.Count() == 1)
        {
            return outputs[0];
        }
        else
        {
            string response = "";
            foreach(string output in outputs)
            {
                response += (output + Environment.NewLine);
            }
            return response;
        }
    }

    private async Task SendTerminalCommand(string command,string tabid)
    {
        Utilities.terminalCommandRecording.TerminalInput[tabid].Enqueue(command);
    }



    private async Task OnShowCommandHistory(KeyboardEventArgs e, TabView tab)
    {
        if (tab.Content.Count > 0)
        {
            //check to make sure the key pressed was the up arrow
            if (e.Code == "ArrowUp")
            {
                HistoryIndex++;
                if (HistoryIndex > (tab.Content.Count - 1))
                {
                    HistoryIndex = (tab.Content.Count - 1);
                }
                //get the Historyindex, set placeholder text to the history item at that index, and increment the index
                if (HistoryIndex <= tab.Content.Count)
                {
                    if (HistoryIndex < 0)
                    {
                        HistoryIndex = 0;
                    }
                    await GetCommandHistory(tab);
                }
            }
            else if (e.Code == "ArrowDown")
            {
                HistoryIndex--;
                if (HistoryIndex < -1)
                {
                    //if index is less than -1 set it to -1 and update the placeholder text to be blank
                    HistoryIndex = -1;
                    TextSuppersion = false; //allows text box to be updated
                    CommandText = "";
                    await Task.Delay(500);
                    TextSuppersion = true; // reset so textbox can be typed in without autoclearing until submission
                }
                //get the Historyindex, set placeholder text to the history item at that index, and decrement the index
                if (HistoryIndex >= 0)
                {
                    await GetCommandHistory(tab);
                }
            }
        }
    }

    private async Task GetCommandHistory(TabView tab)
    {
        TextSuppersion = false; //allows text box to be updated
        CommandText = tab.Content[HistoryIndex].Command;
        await Task.Delay(500);
        TextSuppersion = true; // reset so textbox can be typed in without autoclearing until submission
    }
    


    protected override void OnAfterRender(bool firstRender)
    {
        if (_updateIndex == true)
        {
            UserIndex = UserTabs.Count - 1;
            _updateIndex = false;
            StateHasChanged();
        }
    }

}
